home *** CD-ROM | disk | FTP | other *** search
- unit ReceiveMain;
-
- interface
-
- uses
- Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
- ExtCtrls, OleCtrls, ISP, OLE2, StdCtrls, Menus;
-
- type
- TMainForm = class(TForm)
- Image1: TImage;
- TCP1: TTCP;
- TCP2: TTCP;
- MainMenu1: TMainMenu;
- Connection1: TMenuItem;
- connect1: TMenuItem;
- Disconnect1: TMenuItem;
- File1: TMenuItem;
- Close1: TMenuItem;
- procedure FormCreate(Sender: TObject);
- procedure TCP1DataArrival(Sender: TObject; bytesTotal: Integer);
- procedure FormClose(Sender: TObject; var Action: TCloseAction);
- procedure TCP2ConnectionRequest(Sender: TObject; requestID: Integer);
- procedure TCP1Error(Sender: TObject; Number: Smallint;
- var Description: string; Scode: Integer; const Source,
- HelpFile: string; HelpContext: Integer; var CancelDisplay: Wordbool);
- procedure connect1Click(Sender: TObject);
- procedure Disconnect1Click(Sender: TObject);
- procedure Close1Click(Sender: TObject);
- private
- { Private declarations }
- public
- { Public declarations }
- end;
-
- var
- MainForm: TMainForm;
- Stream : TMemoryStream; // This needs to be static
-
-
- implementation
- {$R *.DFM}
- uses Mmsystem, OneI;
- var
- count : integer = 0;
- pheader : PTFisherTCP = nil;
- head : pbyte = nil;
-
-
- function IsClosed(Tcp1, Tcp2 : TTCP ): Boolean;
- var
- i : integer;
- begin
- {Should do something fancy like a thread that checks memory,
- but this tends to work (as it should not be needed)}
- for i := 1 to 1000 do
- Application.ProcessMessages;
- end;
-
- procedure UseData(Head : PByte; Count, DataType: Integer);
- {This is the function that is called after a complete data transaction
- has occured. It is pretty basic and should be easy to modify. It takes
- This function takes 3 basic parameter, a pointer, a size and a data type,
- I demo a few ways to work with this data.}
- var
- Stream: TMemoryStream;
- FileStream: TFileStream;
- StartUpInfo: TStartUpInfo;
- ProcessInfo: TProcessInformation;
- begin
-
- case DataType of
- OneI_BitMap : begin
- Stream := TMemoryStream.Create;
- try
- Stream.Write(Head^, Count);
- Stream.Seek(0,0);
- with MainForm do begin
- Image1.Picture.Bitmap.LoadFromStream(Stream);
- {Becareful of small bitmaps!!! - you can hang
- But a little extra code could do the trick}
- Width := Image1.Picture.Bitmap.Width;
- Height := Image1.Picture.Bitmap.Height;
- end;
- finally
- Stream.Free;
- end;
- end;
- OneI_Wav : begin
- if not PlaySound (pChar(head), 0, snd_memory) then
- ShowMessage('Received a .wav that could not played')
- end;
- OneI_Exe: begin
- FileStream := TFileStream.Create('c:\sample.exe', fmCreate);
- try
- FileStream.write(head^, Count);
- finally
- FileStream.free;
- end;
- FillChar(StartUpInfo, SizeOf(TStartUpInfo), 0);
- with StartUpInfo do begin
- cb := SizeOf(TStartUpInfo);
- wShowWindow := SW_ShowNormal;
- end;
- CreateProcess('c:\Sample.exe', Nil, Nil, Nil, False,
- NORMAL_PRIORITY_CLASS, Nil, Nil, StartupInfo, ProcessInfo);
-
- {might want to delete the file now - might not...}
- end;
- else
- ShowMessage('What is this Data?');
- end; //case
- end;
-
-
- {TMain.TCP1DataArrival() is the real workhourse of the program. DataArrival()
- is called when incoming packets are received. The programmer does
- not know how many times it will called.}
- procedure TMainForm.TCP1DataArrival(Sender: TObject; bytesTotal: Integer);
- var
- Window : pbyte;
- Ptr: pointer;
- databuffer : variant;
- headerbuffer : variant;
- begin
-
- {Note Pheader will be nil the first time this method is called. We rely
- on this fact to know that the current infomation is a data header, not data.
- So we know the size and layout of the data. Becareful to keep this header
- small so its tranmission does not take more than data transfer}
- if pheader = nil then begin // new data !!
- {New header, get setup}
- pheader := AllocMem(SizeOf(TFisherTCP));
- HeaderBuffer := VarArrayCreate([0,SizeOf(TFisherTCP) -1], varbyte);
- {grab the header record}
- Tcp1.GetData(headerbuffer, (VT_Array or VT_ui1) , SizeOf(TFisherTCP) );
- Try
- {copy the data to my header variable}
- ptr := VarArrayLock(headerbuffer);
- move(Ptr^, pheader^, SizeOf(TFisherTCP));
- Finally
- VarArrayUnlock(HeaderBuffer);
- end;
- {finally allocate a buffer for the data, using a head pointer}
- head := AllocMem(pheader^.size + 1 * sizeof(byte));
- caption := 'Receiving';
- end else begin // pheader is not nil -> means we are grabing data!
- { set up my data structures}
- DataBuffer := VarArrayCreate([0,BytesTotal], varbyte);
- {set my pointer}
- window := head;
- inc(window, count);
- {grab a hunk of data from the port}
- inc(count, Tcp1.BytesReceived);
- Tcp1.GetData(DataBuffer, (VT_Array or VT_ui1 ) , BytesTotal);
- {copy that hunk of data over}
- try
- ptr := VarArrayLock(DataBuffer);
- move(Ptr^, window^, BytesTotal);
- finally
- VarArrayUnlock(DataBuffer);
- end;
-
- {At the end of each data transfer, check to see if this was the last
- transfer...if so, use the data somehow}
- if count = pheader^.size then begin
- UseData(head, count, pheader^.tag);
- {Reset the data connection for the next transfer}
- FreeMem(pheader);
- pheader := nil;
- count := 0;
- FreeMem(head);
- caption := 'Transfer Complete';
- end //if-count
- end; //if-else..(pheader = nil)
- end;
-
- {------ Form methods ------}
- procedure TMainForm.FormClose(Sender: TObject; var Action: TCloseAction);
- begin
- Tcp2.Close;
- Tcp1.Close;
- { Make sure both components are closed - A.V. if they are not.
- The Tcp1.State may report connection are closed after a close -
- but they may or not not be...}
- while not IsClosed(Tcp1, tcp2) do
- application.processMessages;
- end;
-
- procedure TMainForm.FormCreate(Sender: TObject);
- begin
- {Just make sure these controls are closed}
- Tcp1.Close;
- Tcp2.Close;
- end;
-
- {------ TCP control events -----}
- procedure TMainForm.TCP2ConnectionRequest(Sender: TObject;
- requestID: Integer);
- begin
- {Note: these TCP controls can not issue an accept() to
- themselves. So there must be two controls}
- Tcp1.Accept(requestId);
- Tcp2.Close;
- caption := 'Connected';
- end;
-
- procedure TMainForm.TCP1Error(Sender: TObject; Number: Smallint;
- var Description: string; Scode: Integer; const Source, HelpFile: string;
- HelpContext: Integer; var CancelDisplay: Wordbool);
- begin
- {This method does not do much, just closes the TCP controls and
- displays the generic message}
- Tcp1.close;
- Tcp2.close;
- Showmessage(description);
- end;
-
- {---------------- Menu event methods --------------------}
- procedure TMainForm.connect1Click(Sender: TObject);
- begin
- {Sets the application into listen mode}
- connect1.caption := 'Listening';
- connect1.enabled := False;
- connect1.checked := True;
- Tcp2.Listen;
- Disconnect1.enabled := True;
- caption := 'Listening';
- end;
-
- procedure TMainForm.Disconnect1Click(Sender: TObject);
- begin
- {disconnects or stops listening}
- Tcp1.close;
- Tcp2.close;
- Connect1.caption := 'Listen';
- Connect1.checked := False;
- Disconnect1.enabled := False;
- connect1.enabled := True;
- caption := 'Not Connected'
- end;
-
- procedure TMainForm.Close1Click(Sender: TObject);
- begin
- {Close the application}
- Close;
- end;
-
- end.
-